/*********************************************************************
* File: SensesSampleAgent.cpp
*
* Implements the combat and finances API sample. 
*
* \author Instituto Superior Tecnico de Lisboa, Portugal
* \author Technical University of Lisbon, Portugal
* 
* \author Agentes Autonomos e Sistemas Multiagente
* \author Autonomous Agents and Multiagent Systems
* 
* \version	1.0
* \date		2006/2007
*********************************************************************/
#include "SensesSampleAgent.h"
using namespace agents::samples;

#define TIMEOUT_NOT_DEFINED -1

#include "../../util/debug.h"
#include "../../util/util.h"
using namespace util;

SensesSampleAgent::SensesSampleAgent(edict_t *enity, int team, int model)
:Agent(enity, team, model)
{
	_isSeekingGrenades = false;
	_isAiming = false;
	_isPlantingBomb = false;
	_isMovingToTarget = false;
}

SensesSampleAgent::~SensesSampleAgent(){}
void SensesSampleAgent::think()
{
	if(_isSeekingGrenades)
	{
		char msgBuffer[512];
		Vector position;
		if(getVision().isHeGrenadeVisible(&position))
		{
			sprintf(msgBuffer, "I see a HE grenade at: %.2f %.2f %.2f\n", position.x, position.y, position.z);
			_nextSeekGrenadeTime = getWorld().getTime() + 1.5;
			getCommunication().sayText(msgBuffer);
			return;
		}
		else if(getVision().isSmokeGrenadeVisible(&position))
		{
			sprintf(msgBuffer, "I see a smoke grenade at: %.2f %.2f %.2f\n", position.x, position.y, position.z);
			_nextSeekGrenadeTime = getWorld().getTime() + 1.5;
			getCommunication().sayText(msgBuffer);
			return;
		}
		else if(getVision().isFlashbangVisible(&position))
		{
			sprintf(msgBuffer, "I see a flashbang grenade at: %.2f %.2f %.2f\n", position.x, position.y, position.z);
			_nextSeekGrenadeTime = getWorld().getTime() + 1.5;
			getCommunication().sayText(msgBuffer);
			return;
		}
	}

	ICommunication::MessageRecord record;
	if(getCommunication().receiveMsg(ICommunication::SayMessages::sayMsg, &record))
		handleMessage(record);
	else if(getCommunication().receiveMsg(ICommunication::SayMessages::sayTeamMsg, &record))
		handleMessage(record);
	else if(getCommunication().receiveMsg(ICommunication::SayMessages::sayDeadMsg, &record))
		handleMessage(record);
}
void SensesSampleAgent::handleMessage(ICommunication::MessageRecord& record)
{
	char msgBuffer[512];
	char command[32];
	char arg1[32];
	char arg2[32];

	strcpy(arg1, "");
	strcpy(arg2, "");
	sscanf(record.msg, "%s %s %s", command, arg1, arg2);

	if(strcmp(command,"fov")==0)
	{   
		sprintf(msgBuffer, "My field of view is '%.2f' degrees.\n", getVision().getFieldOfView());
		getCommunication().sayText(msgBuffer);
	}
	else if(strcmp(command,"seeT")==0)
	{   
		int count;
		IVision::IVisibleAgent** teammates = getVision().seeTeammates(&count);

		if(count > 0)
		{
			char visibleAgents[512];
			char visibleAgent[128];
			strcpy(visibleAgents, "");
			for(int i = 0; i < count; i++)
			{
				sprintf(visibleAgent, "%s(%d) ", teammates[i]->getName(), teammates[i]->getHealth());
				strcat(visibleAgents, visibleAgent);
			}
			sprintf(msgBuffer, "I see the following teammates: %s\n", visibleAgents);
		}
		else
			sprintf(msgBuffer, "I see no teammates.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if(strcmp(command,"seeE")==0)
	{   
		int count;
		IVision::IVisibleAgent** enemies = getVision().seeEnemies(&count);

		if(count > 0)
		{
			char visibleAgents[512];
			char visibleAgent[128];
			strcpy(visibleAgents, "");
			for(int i = 0; i < count; i++)
			{
				sprintf(visibleAgent, "%s(%d) ", enemies[i]->getName(), enemies[i]->getHealth());
				strcat(visibleAgents, visibleAgent);
			}
			sprintf(msgBuffer, "I see the following enemies: %s\n", visibleAgents);
		}
		else
			sprintf(msgBuffer, "I see no enemies.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if(strcmp(command,"seeR")==0)
	{   
		int count;
		IRadar::RadarUnit* units = getRadar().getRadarVisibleUnits(&count);

		if(count > 0)
		{
			util::debug::printToServer("Visible radar units:\n");
			char buffer[256];
			for(int i = 0; i < count; i++)
			{
				sprintf(buffer, " Distance=%.2f Direction=(%.2f, %.2f, %.2f) isTeammate=%d isBomb=%d isArmedBomb=%d\n", 
					units[i].distance, units[i].direction.x, units[i].direction.y, units[i].direction.z, 
					units[i].isTeammate, units[i].isBomb, units[i].isArmedBomb);
				util::debug::printToServer(buffer);
			}
			sprintf(msgBuffer, "I see %d visible radar units. Details in the console. \n", count);
		}
		else
			sprintf(msgBuffer, "I see no visible radar units.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"weapons")==0) || (strcmp(command,"w")==0))
	{
		int count = 8;
		IVision::PickableWeapon weapons[8];
		getVision().seeWeaponsOnTheFloor(&weapons[0], &count);

		char weaponNames[256];
		WeaponInfo* weaponInfo;
		strcpy(weaponNames, "");
		for(int i=0; i<count; i++)
		{
			weaponInfo = getCombat().getWeaponInfo(weapons[i].weapon);
			strcat(weaponNames, weaponInfo->name);
			strcat(weaponNames, " ");	
		}

		if(count)
			sprintf(msgBuffer, "I see these weapons on the floor: %s\n", weaponNames);
		else
			sprintf(msgBuffer, "I see no weapons on the floor.\n");

		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"droppedBomb")==0) || (strcmp(command,"dB")==0))
	{   
		Vector position;
		if(getVision().isDroppedBombVisible(&position))
			sprintf(msgBuffer, "I see the dropped bomb at: %.2f %.2f %.2f.\n", position.x, position.y, position.z);
		else
			sprintf(msgBuffer, "I don't see the dropped bomb.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"armedBomb")==0) || (strcmp(command,"aB")==0))
	{   
		Vector position;
		if(getVision().isArmedBombVisible(&position))
			sprintf(msgBuffer, "I see the armed bomb at: %.2f %.2f %.2f.\n", position.x, position.y, position.z);
		else
			sprintf(msgBuffer, "I don't see the armed bomb.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"bomber")==0) || (strcmp(command,"b")==0))
	{   
		VisibleAgent bomber;
		if(getVision().isBomberVisible(&bomber))
		{
			Vector position = bomber.getPosition();
			sprintf(msgBuffer, "I see the bomber at: %.2f %.2f %.2f.\n", position.x, position.y, position.z);
		}
		else
			sprintf(msgBuffer, "I don't see the bomber.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"seeDamageInflictor")==0) || (strcmp(command,"seeDI")==0))
	{   
		bool seeDamageInflictor = false;
		char damageInflictorName[64];

		int count;
		IVision::IVisibleAgent** visibleAgents = getVision().seeTeammates(&count);
		if(count > 0)
		{
			for(int i = 0; i < count; i++)
			{
				if(getVision().inflictedDamage(visibleAgents[i]))
				{
					seeDamageInflictor = true;
					strcpy(damageInflictorName, visibleAgents[i]->getName());
					break;
				}
			}
		}
		if(!seeDamageInflictor)
		{
			visibleAgents = getVision().seeEnemies(&count);
			if(count > 0)
			{
				for(int i = 0; i < count; i++)
				{
					if(getVision().inflictedDamage(visibleAgents[i]))
					{
						seeDamageInflictor = true;
						strcpy(damageInflictorName, visibleAgents[i]->getName());
						break;
					}
				}
			}
		}
		
		if(!seeDamageInflictor)
			sprintf(msgBuffer, "I don't see a damage inflictor.\n");
		else
			sprintf(msgBuffer, "I see the damage inflictor. It is %s.\n", damageInflictorName);

		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"hearsBomb")==0) || (strcmp(command,"hB")==0))
	{   
		Vector direction;
		if(getHearing().hearsBomb(&direction))
			sprintf(msgBuffer, "I hear the bomber from: %.2f %.2f %.2f.\n", direction.x, direction.y, direction.z);
		else
			sprintf(msgBuffer, "I don't hear the bomb.\n");
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(record.msg,"moveToHere")==0) || (strcmp(command,"mH")==0))
	{
		Vector senderOrigin = getNavigation().getPosition() + record.sender.radarUnit.direction * record.sender.radarUnit.distance;
		getFreeNavigation().moveToDestination(senderOrigin);
		sprintf(msgBuffer, "Moving towards your current position (%.2f %.2f %.2f)...\n", 
			senderOrigin.x, senderOrigin.y, senderOrigin.z);
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command, "moveToGoal")==0) || (strcmp(command,"mG")==0))
	{
		int destination = getWaypointNavigation().getGoalWaypointIndices()[
			RANDOM_LONG(0, getWaypointNavigation().getNumberOfGoalWaypoints())];
			getWaypointNavigation().moveToWaypoint(destination);
			sprintf(msgBuffer, "Moving to goal waypoint %d...\n", destination);
			getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command, "moveTo")==0)||(strcmp(command, "m")==0))
	{
		if(util::isNullString(arg1))
		{
			util::debug::printToServer("ERROR: Incorrect arguments. Syntax: moveTo <destinationWaypoint>");
			return;
		}

		int destination = atoi(arg1);
		getWaypointNavigation().moveToWaypoint(destination);
		sprintf(msgBuffer, "Moving to waypoint %d.\n", destination);
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"seekGrenades")==0) || (strcmp(command,"sG")==0))
	{
		_isSeekingGrenades = true;
		_nextSeekGrenadeTime = getWorld().getTime();
		sprintf(msgBuffer, "Seeking grenades...\n");
		getCommunication().sayText(msgBuffer);
	}
	else if((strcmp(command,"stopSeekingGrenades")==0) || (strcmp(command,"ssG")==0))
	{
		_isSeekingGrenades = false;
		sprintf(msgBuffer, "Stopped seeking grenades.\n");
		getCommunication().sayText(msgBuffer);
	}
}